package org.example.codeservce.util;

import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.example.codeservce.contr.CodeFrameworks;
import org.example.codeservce.entity.FileCode;
import org.example.codeservce.entity.Order;
import org.example.codeservce.pojo.vo.PromptBigVo;
import org.example.codeservce.pojo.vo.PromptVo;
import org.example.codeservce.pojo.vo.TreeDTO;
import org.example.codeservce.service.CodeAnalysis;
import org.example.codeservce.service.FileCodeService;
import org.example.codeservce.service.OrderService;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.example.codeservce.config.FileConfig.FILEPATH;

/**
 * &#064;author:  Li Qing
 * date: 2024/5/10 11:23
 * description: 代码分析
 */

@Component
@Slf4j
public class CodeAnalysisToolsUtil
{
    @Resource
    private Map<String, CodeAnalysis> codeAnalysisMap;

    @Resource
    private OrderService orderService;

    @Resource
    private FileCodeService fileCodeService;

    /**
     * 代码分析
     *
     * @param fileName 文件名称
     * @param fileCode
     * @param order
     */
    public void codeAnalysisTools(File fileName, Integer type, FileCode fileCode, Order order)
    {
        String unzipFile = ZipUtilQ.unzip(fileName);
        //分析代码结构
        PromptBigVo promptBigVo = codeAnalysisMap.get(CodeFrameworks.getChannel(type).getBeanName()).analysisCodeStructure(unzipFile, order);
        Map<File, String> pageinfos = promptBigVo.getPageinfos();
        List<TreeDTO> objects = pageinfos.keySet().stream().map(key ->
                                                                        new TreeDTO().setPath(key.getAbsolutePath())
                                                                           .setFileName(key.getName())
                                                                           .setResultPrompt(pageinfos.get(key))
                                                               ).collect(Collectors.toList());
        String savedJson = saveJson(promptBigVo, order);
        FileCode pomPromptVo = new FileCode()
                .setId(fileCode.getId())
                .setPageInfos(JSONUtil.toJsonStr(objects))
                .setClassPromptVo(savedJson)
                .setResourcesPromptVo(JSONUtil.toJsonStr(promptBigVo.getResourcesPromptVo()))
                .setFilePath(unzipFile)
                .setStatus(1)
                .setPomPromptVo(JSONUtil.toJsonStr(promptBigVo.getPomPromptVo()));
        fileCodeService.updateById(
                pomPromptVo
        );
        orderService.updateById(new Order()
                                        .setId(order.getId())
                                        .setStatus(2)
                                        .setFcId(pomPromptVo.getId())
        );
        new Thread(() ->
                   {
                       log.info("源码清理中...");
                       fileName.delete();
                       deleteDirectory(new File(unzipFile));
                   }).start();
    }

    public static void deleteDirectory(File directory)
    {
        if (directory.isDirectory())
        {
            for (File child : directory.listFiles())
            {
                // 递归删除子文件和子目录
                deleteDirectory(child);
            }
        }
        directory.delete(); // 在JVM退出时删除当前目录
    }

    @SneakyThrows
    private static String saveJson(PromptBigVo promptBigVo, Order order)
    {
        File path = new File(FILEPATH + order.getOrderNo() + "/classPromptVo.json");
        // 确保父目录存在
        if (!path.getParentFile().exists())
        {
            path.getParentFile().mkdirs();
        }

        try (BufferedWriter writer = new BufferedWriter(new FileWriter(path)))
        {
            writer.write(JSONUtil.toJsonStr(promptBigVo.getClassPromptVo()));
        } catch (IOException e)
        {
            // 使用日志框架记录异常，示例使用slf4j风格
            log.error("写入文件时出现错误: {}", e.getMessage(), e);
            // 根据业务需求决定是否抛出异常或如何处理
        }
        return path.getName();
    }
}
